home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / demos / 198 / window.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-08-20  |  20.3 KB  |  748 lines

  1. /*
  2.  * Window management. Some of the functions are internal, and some are
  3.  * attached to keys that the user actually types.
  4.  */
  5.  
  6. #include        <stdio.h>
  7. #include        "estruct.h"
  8. #include    "etype.h"
  9. #include    "edef.h"
  10. #include    "elang.h"
  11.  
  12. /*
  13.  * Reposition dot in the current window to line "n". If the argument is
  14.  * positive, it is that line. If it is negative it is that line from the
  15.  * bottom. If it is 0 the window is centered (this is what the standard
  16.  * redisplay code does). With no argument it defaults to 0. Bound to M-!.
  17.  */
  18. PASCAL NEAR reposition(f, n)
  19.     {
  20.     if (f == FALSE)    /* default to 0 to center screen */
  21.     n = 0;
  22.     curwp->w_force = n;
  23.     curwp->w_flag |= WFFORCE;
  24.     return (TRUE);
  25.     }
  26.  
  27. /*
  28.  * Refresh the screen. With no argument, it just does the refresh. With an
  29.  * argument it recenters "." in the current window. Bound to "C-L".
  30.  */
  31. PASCAL NEAR refresh(f, n)
  32.     {
  33.     if (f == FALSE)
  34.         sgarbf = TRUE;
  35.     else
  36.         {
  37.         curwp->w_force = 0;             /* Center dot. */
  38.         curwp->w_flag |= WFFORCE;
  39.         }
  40.  
  41.     return (TRUE);
  42.     }
  43.  
  44. /*
  45.  * The command make the next window (next => down the screen) the current
  46.  * window. There are no real errors, although the command does nothing if
  47.  * there is only 1 window on the screen. Bound to "C-X C-N".
  48.  *
  49.  * with an argument this command finds the <n>th window from the top
  50.  *
  51.  */
  52. PASCAL NEAR nextwind(f, n)
  53.  
  54. int f, n;    /* default flag and numeric argument */
  55.  
  56. {
  57.     register WINDOW *wp;
  58.     register int nwindows;        /* total number of windows */
  59.  
  60.     if (f) {
  61.  
  62.         /* first count the # of windows */
  63.         wp = wheadp;
  64.         nwindows = 1;
  65.         while (wp->w_wndp != NULL) {
  66.             nwindows++;
  67.             wp = wp->w_wndp;
  68.         }
  69.  
  70.         /* if the argument is negative, it is the nth window
  71.            from the bottom of the screen            */
  72.         if (n < 0)
  73.             n = nwindows + n + 1;
  74.  
  75.         /* if an argument, give them that window from the top */
  76.         if (n > 0 && n <= nwindows) {
  77.             wp = wheadp;
  78.             while (--n)
  79.                 wp = wp->w_wndp;
  80.         } else {
  81.             mlwrite(TEXT203);
  82. /*                              "Window number out of range" */
  83.             return(FALSE);
  84.         }
  85.     } else
  86.         if ((wp = curwp->w_wndp) == NULL)
  87.             wp = wheadp;
  88.     curwp = wp;
  89.     curbp = wp->w_bufp;
  90.     upmode();
  91.     return (TRUE);
  92. }
  93.  
  94. /*
  95.  * This command makes the previous window (previous => up the screen) the
  96.  * current window. There arn't any errors, although the command does not do a
  97.  * lot if there is 1 window.
  98.  */
  99. PASCAL NEAR prevwind(f, n)
  100. {
  101.     register WINDOW *wp1;
  102.     register WINDOW *wp2;
  103.  
  104.     /* if we have an argument, we mean the nth window from the bottom */
  105.     if (f)
  106.         return(nextwind(f, -n));
  107.  
  108.     wp1 = wheadp;
  109.     wp2 = curwp;
  110.  
  111.     if (wp1 == wp2)
  112.         wp2 = NULL;
  113.  
  114.     while (wp1->w_wndp != wp2)
  115.         wp1 = wp1->w_wndp;
  116.  
  117.     curwp = wp1;
  118.     curbp = wp1->w_bufp;
  119.     upmode();
  120.     return (TRUE);
  121. }
  122.  
  123. /*
  124.  * This command moves the current window down by "arg" lines. Recompute the
  125.  * top line in the window. The move up and move down code is almost completely
  126.  * the same; most of the work has to do with reframing the window, and picking
  127.  * a new dot. We share the code by having "move down" just be an interface to
  128.  * "move up". Magic. Bound to "C-X C-N".
  129.  */
  130. PASCAL NEAR mvdnwind(f, n)
  131.  
  132. int n;
  133.  
  134. {
  135.     return (mvupwind(f, -n));
  136. }
  137.  
  138. /*
  139.  * Move the current window up by "arg" lines. Recompute the new top line of
  140.  * the window. Look to see if "." is still on the screen. If it is, you win.
  141.  * If it isn't, then move "." to center it in the new framing of the window
  142.  * (this command does not really move "."; it moves the frame). Bound to
  143.  * "C-X C-P".
  144.  */
  145. PASCAL NEAR mvupwind(f, n)
  146.     int n;
  147.  
  148.     {
  149.     register LINE *lp;
  150.     register int i;
  151.  
  152.     lp = curwp->w_linep;
  153.  
  154.     if (n < 0)
  155.         {
  156.         while (n++ && lp!=curbp->b_linep)
  157.             lp = lforw(lp);
  158.         }
  159.     else
  160.         {
  161.         while (n-- && lback(lp)!=curbp->b_linep)
  162.             lp = lback(lp);
  163.         }
  164.  
  165.     curwp->w_linep = lp;
  166.     curwp->w_flag |= WFHARD;            /* Mode line is OK. */
  167.  
  168.     for (i = 0; i < curwp->w_ntrows; ++i)
  169.         {
  170.         if (lp == curwp->w_dotp)
  171.             return (TRUE);
  172.         if (lp == curbp->b_linep)
  173.             break;
  174.         lp = lforw(lp);
  175.         }
  176.  
  177.     lp = curwp->w_linep;
  178.     i  = curwp->w_ntrows/2;
  179.  
  180.     while (i-- && lp != curbp->b_linep)
  181.         lp = lforw(lp);
  182.  
  183.     curwp->w_dotp  = lp;
  184.     curwp->w_doto  = 0;
  185.     return (TRUE);
  186.     }
  187.  
  188. /*
  189.  * This command makes the current window the only window on the screen. Bound
  190.  * to "C-X 1". Try to set the framing so that "." does not have to move on the
  191.  * display. Some care has to be taken to keep the values of dot and mark in
  192.  * the buffer structures right if the distruction of a window makes a buffer
  193.  * become undisplayed.
  194.  */
  195. PASCAL NEAR onlywind(f, n)
  196. {
  197.         register WINDOW *wp;
  198.         register LINE   *lp;
  199.         register int    i;
  200.     int cmark;        /* current mark */
  201.  
  202.         while (wheadp != curwp) {
  203.                 wp = wheadp;
  204.                 wheadp = wp->w_wndp;
  205.                 if (--wp->w_bufp->b_nwnd == 0) {
  206.                         wp->w_bufp->b_dotp  = wp->w_dotp;
  207.                         wp->w_bufp->b_doto  = wp->w_doto;
  208.             for (cmark = 0; cmark < NMARKS; cmark++) {
  209.                             wp->w_bufp->b_markp[cmark] = wp->w_markp[cmark];
  210.                             wp->w_bufp->b_marko[cmark] = wp->w_marko[cmark];
  211.                         }
  212.                         wp->w_bufp->b_fcol  = wp->w_fcol;
  213.                 }
  214.                 free((char *) wp);
  215.         }
  216.         while (curwp->w_wndp != NULL) {
  217.                 wp = curwp->w_wndp;
  218.                 curwp->w_wndp = wp->w_wndp;
  219.                 if (--wp->w_bufp->b_nwnd == 0) {
  220.                         wp->w_bufp->b_dotp  = wp->w_dotp;
  221.                         wp->w_bufp->b_doto  = wp->w_doto;
  222.             for (cmark = 0; cmark < NMARKS; cmark++) {
  223.                             wp->w_bufp->b_markp[cmark] = wp->w_markp[cmark];
  224.                             wp->w_bufp->b_marko[cmark] = wp->w_marko[cmark];
  225.                         }
  226.                         wp->w_bufp->b_fcol  = wp->w_fcol;
  227.                 }
  228.                 free((char *) wp);
  229.         }
  230.         lp = curwp->w_linep;
  231.         i  = curwp->w_toprow;
  232.         while (i!=0 && lback(lp)!=curbp->b_linep) {
  233.                 --i;
  234.                 lp = lback(lp);
  235.         }
  236.         curwp->w_toprow = 0;
  237.         curwp->w_ntrows = term.t_nrow-1;
  238.         curwp->w_linep  = lp;
  239.         curwp->w_flag  |= WFMODE|WFHARD;
  240.         return (TRUE);
  241. }
  242.  
  243. /*
  244.  * Delete the current window, placing its space in the window above,
  245.  * or, if it is the top window, the window below. Bound to C-X 0.
  246.  */
  247.  
  248. PASCAL NEAR delwind(f,n)
  249.  
  250. int f, n;    /* arguments are ignored for this command */
  251.  
  252. {
  253.     register WINDOW *wp;    /* window to recieve deleted space */
  254.     register WINDOW *lwp;    /* ptr window before curwp */
  255.     register int target;    /* target line to search for */
  256.     int cmark;        /* current mark */
  257.  
  258.     /* if there is only one window, don't delete it */
  259.     if (wheadp->w_wndp == NULL) {
  260.         mlwrite(TEXT204);
  261. /*                      "Can not delete this window" */
  262.         return(FALSE);
  263.     }
  264.  
  265.     /* find window before curwp in linked list */
  266.     wp = wheadp;
  267.     lwp = NULL;
  268.     while (wp != NULL) {
  269.         if (wp == curwp)
  270.             break;
  271.         lwp = wp;
  272.         wp = wp->w_wndp;
  273.     }
  274.  
  275.     /* find recieving window and give up our space */
  276.     wp = wheadp;
  277.     if (curwp->w_toprow == 0) {
  278.         /* find the next window down */
  279.         target = curwp->w_ntrows + 1;
  280.         while (wp != NULL) {
  281.             if (wp->w_toprow == target)
  282.                 break;
  283.             wp = wp->w_wndp;
  284.         }
  285.         if (wp == NULL)
  286.             return(FALSE);
  287.         wp->w_toprow = 0;
  288.         wp->w_ntrows += target;
  289.     } else {
  290.         /* find the next window up */
  291.         target = curwp->w_toprow - 1;
  292.         while (wp != NULL) {
  293.             if ((wp->w_toprow + wp->w_ntrows) == target)
  294.                 break;
  295.             wp = wp->w_wndp;
  296.         }
  297.         if (wp == NULL)
  298.             return(FALSE);
  299.         wp->w_ntrows += 1 + curwp->w_ntrows;
  300.     }
  301.  
  302.     /* get rid of the current window */
  303.     if (--curwp->w_bufp->b_nwnd == 0) {
  304.         curwp->w_bufp->b_dotp  = curwp->w_dotp;
  305.         curwp->w_bufp->b_doto  = curwp->w_doto;
  306.         for (cmark = 0; cmark < NMARKS; cmark++) {
  307.             curwp->w_bufp->b_markp[cmark] = curwp->w_markp[cmark];
  308.             curwp->w_bufp->b_marko[cmark] = curwp->w_marko[cmark];
  309.         }
  310.         curwp->w_bufp->b_fcol  = curwp->w_fcol;
  311.     }
  312.     if (lwp == NULL)
  313.         wheadp = curwp->w_wndp;
  314.     else
  315.         lwp->w_wndp = curwp->w_wndp;
  316.     free((char *)curwp);
  317.     curwp = wp;
  318.     wp->w_flag |= WFHARD;
  319.     curbp = wp->w_bufp;
  320.     upmode();
  321.     return(TRUE);
  322. }
  323.  
  324. /*
  325.  
  326. Split the current window.  A window smaller than 3 lines cannot be
  327. split.  (Two line windows can be split when mode lines are disabled) An
  328. argument of 1 forces the cursor into the upper window, an argument of
  329. two forces the cursor to the lower window.  The only other error that
  330. is possible is a "malloc" failure allocating the structure for the new
  331. window.  Bound to "C-X 2". 
  332.  
  333. */
  334.  
  335. PASCAL NEAR splitwind(f, n)
  336.  
  337. int f, n;    /* default flag and numeric argument */
  338.  
  339. {
  340.         register WINDOW *wp;
  341.         register LINE   *lp;
  342.         register int    ntru;
  343.         register int    ntrl;
  344.         register int    ntrd;
  345.         register WINDOW *wp1;
  346.         register WINDOW *wp2;
  347.     int cmark;        /* current mark */
  348.  
  349.     /* make sure we have enough space */
  350.         if (curwp->w_ntrows < (modeflag ? 3 : 2)) {
  351.                 mlwrite(TEXT205, curwp->w_ntrows);
  352. /*                      "Cannot split a %d line window" */
  353.                 return (FALSE);
  354.         }
  355.         if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL) {
  356.                 mlwrite(TEXT99);
  357. /*                      "[OUT OF MEMORY]" */
  358.                 return (FALSE);
  359.         }
  360.         ++curbp->b_nwnd;                        /* Displayed twice.     */
  361.         wp->w_bufp  = curbp;
  362.         wp->w_dotp  = curwp->w_dotp;
  363.         wp->w_doto  = curwp->w_doto;
  364.     for (cmark = 0; cmark < NMARKS; cmark++) {
  365.             wp->w_markp[cmark] = curwp->w_markp[cmark];
  366.             wp->w_marko[cmark] = curwp->w_marko[cmark];
  367.         }
  368.     wp->w_fcol  = curwp->w_fcol;
  369.         wp->w_flag  = 0;
  370.         wp->w_force = 0;
  371. #if    COLOR
  372.     /* set the colors of the new window */
  373.     wp->w_fcolor = gfcolor;
  374.     wp->w_bcolor = gbcolor;
  375. #endif
  376.         ntru = (curwp->w_ntrows-1) / 2;         /* Upper size           */
  377.         ntrl = (curwp->w_ntrows-1) - ntru;      /* Lower size           */
  378.         lp = curwp->w_linep;
  379.         ntrd = 0;
  380.         while (lp != curwp->w_dotp) {
  381.                 ++ntrd;
  382.                 lp = lforw(lp);
  383.         }
  384.         lp = curwp->w_linep;
  385.         if (((f == FALSE) && (ntrd <= ntru)) || ((f == TRUE) && (n == 1))) {
  386.                 /* Old is upper window. */
  387.                 if (ntrd == ntru)               /* Hit mode line.       */
  388.                         lp = lforw(lp);
  389.                 curwp->w_ntrows = ntru;
  390.                 wp->w_wndp = curwp->w_wndp;
  391.                 curwp->w_wndp = wp;
  392.                 wp->w_toprow = curwp->w_toprow+ntru+1;
  393.                 wp->w_ntrows = ntrl;
  394.         } else {                                /* Old is lower window  */
  395.                 wp1 = NULL;
  396.                 wp2 = wheadp;
  397.                 while (wp2 != curwp) {
  398.                         wp1 = wp2;
  399.                         wp2 = wp2->w_wndp;
  400.                 }
  401.                 if (wp1 == NULL)
  402.                         wheadp = wp;
  403.                 else
  404.                         wp1->w_wndp = wp;
  405.                 wp->w_wndp   = curwp;
  406.                 wp->w_toprow = curwp->w_toprow;
  407.                 wp->w_ntrows = ntru;
  408.                 ++ntru;                         /* Mode line.           */
  409.                 curwp->w_toprow += ntru;
  410.                 curwp->w_ntrows  = ntrl;
  411.                 while (ntru--)
  412.                         lp = lforw(lp);
  413.         }
  414.         curwp->w_linep = lp;                    /* Adjust the top lines */
  415.         wp->w_linep = lp;                       /* if necessary.        */
  416.         curwp->w_flag |= WFMODE|WFHARD;
  417.         wp->w_flag |= WFMODE|WFHARD;
  418.         return (TRUE);
  419. }
  420.  
  421. /*
  422.  * Enlarge the current window. Find the window that loses space. Make sure it
  423.  * is big enough. If so, hack the window descriptions, and ask redisplay to do
  424.  * all the hard work. You don't just set "force reframe" because dot would
  425.  * move. Bound to "C-X Z".
  426.  */
  427. PASCAL NEAR enlargewind(f, n)
  428. {
  429.         register WINDOW *adjwp;
  430.         register LINE   *lp;
  431.         register int    i;
  432.  
  433.         if (n < 0)
  434.                 return (shrinkwind(f, -n));
  435.         if (wheadp->w_wndp == NULL) {
  436.                 mlwrite(TEXT206);
  437. /*                      "Only one window" */
  438.                 return (FALSE);
  439.         }
  440.         if ((adjwp=curwp->w_wndp) == NULL) {
  441.                 adjwp = wheadp;
  442.                 while (adjwp->w_wndp != curwp)
  443.                         adjwp = adjwp->w_wndp;
  444.         }
  445.         if ((adjwp->w_ntrows + (modeflag ? 0 : 1)) <= n) {
  446.                 mlwrite(TEXT207);
  447. /*                      "Impossible change" */
  448.                 return (FALSE);
  449.         }
  450.         if (curwp->w_wndp == adjwp) {           /* Shrink below.        */
  451.                 lp = adjwp->w_linep;
  452.                 for (i=0; i<n && lp!=adjwp->w_bufp->b_linep; ++i)
  453.                         lp = lforw(lp);
  454.                 adjwp->w_linep  = lp;
  455.                 adjwp->w_toprow += n;
  456.         } else {                                /* Shrink above.        */
  457.                 lp = curwp->w_linep;
  458.                 for (i=0; i<n && lback(lp)!=curbp->b_linep; ++i)
  459.                         lp = lback(lp);
  460.                 curwp->w_linep  = lp;
  461.                 curwp->w_toprow -= n;
  462.         }
  463.         curwp->w_ntrows += n;
  464.         adjwp->w_ntrows -= n;
  465.         curwp->w_flag |= WFMODE|WFHARD;
  466.         adjwp->w_flag |= WFMODE|WFHARD;
  467.         return (TRUE);
  468. }
  469.  
  470. /*
  471.  * Shrink the current window. Find the window that gains space. Hack at the
  472.  * window descriptions. Ask the redisplay to do all the hard work. Bound to
  473.  * "C-X C-Z".
  474.  */
  475. PASCAL NEAR shrinkwind(f, n)
  476. {
  477.         register WINDOW *adjwp;
  478.         register LINE   *lp;
  479.         register int    i;
  480.  
  481.         if (n < 0)
  482.                 return (enlargewind(f, -n));
  483.         if (wheadp->w_wndp == NULL) {
  484.                 mlwrite(TEXT206);
  485. /*                      "Only one window" */
  486.                 return (FALSE);
  487.         }
  488.         if ((adjwp=curwp->w_wndp) == NULL) {
  489.                 adjwp = wheadp;
  490.                 while (adjwp->w_wndp != curwp)
  491.                         adjwp = adjwp->w_wndp;
  492.         }
  493.         if ((curwp->w_ntrows + (modeflag ? 0 : 1)) <= n) {
  494.                 mlwrite(TEXT207);
  495. /*                      "Impossible change" */
  496.                 return (FALSE);
  497.         }
  498.         if (curwp->w_wndp == adjwp) {           /* Grow below.          */
  499.                 lp = adjwp->w_linep;
  500.                 for (i=0; i<n && lback(lp)!=adjwp->w_bufp->b_linep; ++i)
  501.                         lp = lback(lp);
  502.                 adjwp->w_linep  = lp;
  503.                 adjwp->w_toprow -= n;
  504.         } else {                                /* Grow above.          */
  505.                 lp = curwp->w_linep;
  506.                 for (i=0; i<n && lp!=curbp->b_linep; ++i)
  507.                         lp = lforw(lp);
  508.                 curwp->w_linep  = lp;
  509.                 curwp->w_toprow += n;
  510.         }
  511.         curwp->w_ntrows -= n;
  512.         adjwp->w_ntrows += n;
  513.         curwp->w_flag |= WFMODE|WFHARD;
  514.         adjwp->w_flag |= WFMODE|WFHARD;
  515.         return (TRUE);
  516. }
  517.  
  518. /*    Resize the current window to the requested size    */
  519.  
  520. PASCAL NEAR resize(f, n)
  521.  
  522. int f, n;    /* default flag and numeric argument */
  523.  
  524. {
  525.     int clines;    /* current # of lines in window */
  526.     
  527.     /* must have a non-default argument, else ignore call */
  528.     if (f == FALSE)
  529.         return(TRUE);
  530.  
  531.     /* find out what to do */
  532.     clines = curwp->w_ntrows;
  533.  
  534.     /* already the right size? */
  535.     if (clines == n)
  536.         return(TRUE);
  537.  
  538.     return(enlargewind(TRUE, n - clines));
  539. }
  540.  
  541. /*
  542.  * Pick a window for a pop-up. Split the screen if there is only one window.
  543.  * Pick the uppermost window that isn't the current window. An LRU algorithm
  544.  * might be better. Return a pointer, or NULL on error.
  545.  */
  546.  
  547. WINDOW *PASCAL NEAR wpopup()
  548.  
  549. {
  550.         register WINDOW *wp;
  551.  
  552.         if (wheadp->w_wndp == NULL              /* Only 1 window        */
  553.         && splitwind(FALSE, 0) == FALSE)        /* and it won't split   */
  554.                 return (NULL);
  555.         wp = wheadp;                            /* Find window to use   */
  556.         while (wp!=NULL && wp==curwp)
  557.                 wp = wp->w_wndp;
  558.         return (wp);
  559. }
  560.  
  561. PASCAL NEAR nextup(f, n)    /* scroll the next window up (back) a page */
  562.  
  563. {
  564.     nextwind(FALSE, 1);
  565.     backpage(f, n);
  566.     prevwind(FALSE, 1);
  567. }
  568.  
  569. PASCAL NEAR nextdown(f, n)    /* scroll the next window down (forward) a page */
  570.  
  571. {
  572.     nextwind(FALSE, 1);
  573.     forwpage(f, n);
  574.     prevwind(FALSE, 1);
  575. }
  576.  
  577. PASCAL NEAR savewnd(f, n)    /* save ptr to current window */
  578.  
  579. {
  580.     swindow = curwp;
  581.     return(TRUE);
  582. }
  583.  
  584. PASCAL NEAR restwnd(f, n)    /* restore the saved screen */
  585.  
  586. {
  587.     register WINDOW *wp;
  588.  
  589.     /* find the window */
  590.     wp = wheadp;
  591.     while (wp != NULL) {
  592.         if (wp == swindow) {
  593.             curwp = wp;
  594.             curbp = wp->w_bufp;
  595.             upmode();
  596.             return (TRUE);
  597.         }
  598.         wp = wp->w_wndp;
  599.     }
  600.  
  601.     mlwrite(TEXT208);
  602. /*              "[No such window exists]" */
  603.     return(FALSE);
  604. }
  605.  
  606. PASCAL NEAR newsize(f, n)    /* resize the screen, re-writing the screen */
  607.  
  608. int f;    /* default flag */
  609. int n;    /* numeric argument */
  610.  
  611. {
  612.     WINDOW *wp;    /* current window being examined */
  613.     WINDOW *nextwp;    /* next window to scan */
  614.     WINDOW *lastwp;    /* last window scanned */
  615.     int lastline;    /* screen line of last line of current window */
  616.     int cmark;        /* current mark */
  617.  
  618.     /* if the command defaults, assume the largest */
  619.     if (f == FALSE)
  620.         n = term.t_mrow + 1;
  621.  
  622.     /* make sure it's in range */
  623.     if (n < 3 || n > term.t_mrow + 1) {
  624.         mlwrite(TEXT209);
  625. /*                      "%%Screen size out of range" */
  626.         return(FALSE);
  627.     }
  628.  
  629.     if (term.t_nrow == n - 1)
  630.         return(TRUE);
  631.     else if (term.t_nrow < n - 1) {
  632.  
  633.         /* go to the last window */
  634.         wp = wheadp;
  635.         while (wp->w_wndp != NULL)
  636.             wp = wp->w_wndp;
  637.  
  638.         /* and enlarge it as needed */
  639.         wp->w_ntrows = n - wp->w_toprow - 2;
  640.         wp->w_flag |= WFHARD|WFMODE;
  641.  
  642.     } else {
  643.  
  644.         /* rebuild the window structure */
  645.         nextwp = wheadp;
  646.         wp = NULL;
  647.         lastwp = NULL;
  648.         while (nextwp != NULL) {
  649.             wp = nextwp;
  650.             nextwp = wp->w_wndp;
  651.     
  652.             /* get rid of it if it is too low */
  653.             if (wp->w_toprow > n - 2) {
  654.  
  655.                 /* save the point/mark if needed */
  656.                 if (--wp->w_bufp->b_nwnd == 0) {
  657.                     wp->w_bufp->b_dotp = wp->w_dotp;
  658.                     wp->w_bufp->b_doto = wp->w_doto;
  659.                     for (cmark = 0; cmark < NMARKS; cmark++) {
  660.                         wp->w_bufp->b_markp[cmark] = wp->w_markp[cmark];
  661.                         wp->w_bufp->b_marko[cmark] = wp->w_marko[cmark];
  662.                     }
  663.                     wp->w_bufp->b_fcol = wp->w_fcol;
  664.                 }
  665.     
  666.                 /* update curwp and lastwp if needed */
  667.                 if (wp == curwp)
  668.                     curwp = wheadp;
  669.                     curbp = curwp->w_bufp;
  670.                 if (lastwp != NULL)
  671.                     lastwp->w_wndp = NULL;
  672.  
  673.                 /* free the structure */
  674.                 free((char *)wp);
  675.                 wp = NULL;
  676.  
  677.             } else {
  678.                 /* need to change this window size? */
  679.                 lastline = wp->w_toprow + wp->w_ntrows - 1;
  680.                 if (lastline >= n - 2) {
  681.                     wp->w_ntrows = n - wp->w_toprow - 2;
  682.                     wp->w_flag |= WFHARD|WFMODE;
  683.                 }
  684.             }
  685.     
  686.             lastwp = wp;
  687.         }
  688.     }
  689.  
  690.     /* screen is garbage */
  691.     term.t_nrow = n - 1;
  692.     sgarbf = TRUE;
  693.     return(TRUE);
  694. }
  695.  
  696. PASCAL NEAR newwidth(f, n)    /* resize the screen, re-writing the screen */
  697.  
  698. int f;    /* default flag */
  699. int n;    /* numeric argument */
  700.  
  701. {
  702.     register WINDOW *wp;
  703.  
  704.     /* if the command defaults, assume the largest */
  705.     if (f == FALSE)
  706.         n = term.t_mcol;
  707.  
  708.     /* make sure it's in range */
  709.     if (n < 10 || n > term.t_mcol) {
  710.         mlwrite(TEXT210);
  711. /*                      "%%Screen width out of range" */
  712.         return(FALSE);
  713.     }
  714.  
  715.     /* otherwise, just re-width it (no big deal) */
  716.     term.t_ncol = n;
  717.     term.t_margin = n / 10;
  718.     term.t_scrsiz = n - (term.t_margin * 2);
  719.  
  720.     /* florce all windows to redraw */
  721.     wp = wheadp;
  722.     while (wp) {
  723.         wp->w_flag |= WFHARD | WFMOVE | WFMODE;
  724.         wp = wp->w_wndp;
  725.     }
  726.     sgarbf = TRUE;
  727.  
  728.     return(TRUE);
  729. }
  730.  
  731. int PASCAL NEAR getwpos()    /* get screen offset of current line in current window */
  732.  
  733. {
  734.     register int sline;    /* screen line from top of window */
  735.     register LINE *lp;    /* scannile line pointer */
  736.  
  737.     /* search down the line we want */
  738.     lp = curwp->w_linep;
  739.     sline = 1;
  740.     while (lp != curwp->w_dotp) {
  741.         ++sline;
  742.         lp = lforw(lp);
  743.     }
  744.  
  745.     /* and return the value */
  746.     return(sline);
  747. }
  748.